<?php


namespace App\Services\Role;

use App\Common\ResponseCode;
use App\Exceptions\BusinessException;
use App\Models\Base\Resource;
use App\Models\Role\Role;
use App\Models\Role\RoleResourceBind;
use App\Params\Backend\RoleListParam;
use App\Params\Backend\RoleUpdateMenuParam;
use App\Params\Backend\RoleUpdateParam;
use App\Params\Backend\RoleUpdateResourceParam;
use App\Repository\ResourceRepository;
use App\Repository\RoleRepository;
use App\Services\BaseService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * 角色相关业务类
 *
 * @author WangBin
 * @date 2021-09-24
 * @package App\Http\Services
 */
class RoleService extends BaseService
{
    /**
     * 保存角色信息
     *
     * @param RoleUpdateParam $param
     * @return mixed
     * @throws BusinessException
     */
    public function update(RoleUpdateParam $param)
    {
        if($param->getRoleId()) {
            $role = RoleRepository::getInstance()->getById($param->getRoleId());
            if(is_null($role)) {
                throw new BusinessException(ResponseCode::ROLE_NOT_FOUND);
            }
        }
        // 角色编号须唯一
        if(RoleRepository::getInstance()->checkRoleBn($param->getRoleBn(), $param->getRoleId())) {
            throw new BusinessException(ResponseCode::ROLE_BN_EXIST);
        }
        // 角色名称须唯一
        if(RoleRepository::getInstance()->checkRoleName($param->getRoleName(), $param->getRoleId())) {
            throw new BusinessException(ResponseCode::ROLE_BN_EXIST);
        }
        return RoleRepository::getInstance()->update($param->toArray(), $param->getRoleId());
    }

    /**
     * 绑定角色菜单
     *
     * @param RoleUpdateMenuParam $param
     * @return bool
     * @throws BusinessException
     */
    public function updateMenu(RoleUpdateMenuParam $param)
    {
        try {
            DB::beginTransaction();
            ResourceRepository::getInstance()->deleteMenuByRoleId($param->getRoleId());
            RoleRepository::getInstance()->updateMenu($param->getMenuId(), $param->getRoleId());
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            Log::error("[角色菜单绑定] 出错：{$exception->getMessage()}");
            throw new BusinessException(ResponseCode::ROLE_BIND_MENU_FAIL);
        }
        return true;
    }

    /**
     * 角色列表
     *
     * @param RoleListParam $filter
     * @return array
     */
    public function getList(RoleListParam $filter)
    {
        return $this->toList(RoleRepository::getInstance()->getList($filter->toArray()), $filter->getPage(), $filter->getPageSize());
    }

    /**
     * 删除角色
     *
     * @param int $roleId
     * @return mixed
     */
    public function delete(int $roleId)
    {
        return RoleRepository::getInstance()->delete($roleId);
    }

    /**
     * 停用/启用角色
     *
     * @param int $roleId
     * @return int
     * @throws BusinessException
     */
    public function enable(int $roleId)
    {
        $role = RoleRepository::getInstance()->getById($roleId);
        if(is_null($role)) {
            throw new BusinessException(ResponseCode::ROLE_NOT_FOUND);
        }
        $isActive = $role->is_active == 0 ? 1 : 0;
        return RoleRepository::getInstance()->update(['is_active' => $isActive], $roleId);
    }

    /**
     * 获取角色详情
     *
     * @param int $roleId
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws BusinessException
     */
    public function get(int $roleId)
    {
        $role = RoleRepository::getInstance()->getById($roleId);
        if(is_null($role)) {
            throw new BusinessException(ResponseCode::ROLE_NOT_FOUND);
        }
        return $role;
    }

    /**
     * 获取角色的绑定资源
     *
     * @param int $roleId
     * @return array
     */
    public function getResourceBind(int $roleId)
    {
        $bindResource = ResourceRepository::getInstance()->getBindList($roleId)->get();
        return $bindResource->pluck('resource_id')->toArray();
    }

    /**
     * 绑定角色和资源
     *
     * @param RoleUpdateResourceParam $param
     * @return bool
     * @throws BusinessException
     */
    public function updateResource(RoleUpdateResourceParam $param)
    {
        try {
            DB::beginTransaction();
            ResourceRepository::getInstance()->deleteByRoleId($param->getRoleId());
            ResourceRepository::getInstance()->updateResource($param->getResourceId(), $param->getRoleId());
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            Log::error("[角色资源绑定] 出错：{$exception->getMessage()}");
            throw new BusinessException(ResponseCode::ROLE_BIND_RESOURCE_FAIL);
        }
        return true;
    }

    /**
     * 获取角色绑定的菜单 Id
     *
     * @param int $roleId
     * @return \Illuminate\Support\Collection
     */
    public function getMenuBind(int $roleId)
    {
        return RoleRepository::getInstance()->getRoleMenu($roleId)->pluck('menu_id');
    }
}
